package admin

import (
	j_log "config-client-v1/init/j-log"
	"config-client-v1/model"
	"config-client-v1/utils/tools"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"gorm.io/gorm"
)

type FrameController struct {
}

func (con FrameController) List(ctx *gin.Context) {
	param := struct {
		Name  string `json:"name"`
		PPEID int    `json:"ppe_id"`
		model.QueryData
	}{}
	err := ctx.ShouldBindBodyWith(&param, binding.JSON)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的参数",
			"data":    err.Error(),
		})
		return
	}

	tx := model.DB.Where("del = 0")
	if param.PPEID != 0 {
		tx.Where("ppe_id = ?", param.PPEID)
	}
	if param.Name != "" {
		tx.Where("name = ?", param.Name)
	}
	var count int64
	list := make([]*model.Frame, 0)
	err = tx.Model(&model.Frame{}).Count(&count).Error
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    6,
			"message": err.Error(),
		})
		return
	}
	err = tx.Order("id desc").Offset(param.StartPage()).Limit(param.PageSize).Find(&list).Error
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    6,
			"message": err.Error(),
		})
		return
	}
	for _, row := range list {
		row.FrameItemParam = make([]*model.FrameItemParam, 0)
		err = json.Unmarshal([]byte(row.JsonDetail), &row.FrameItemParam)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    2,
				"message": fmt.Sprintf("frame_id=%d %s%v", row.ID, "JsonDetail解析失败", err.Error()),
			})
			return
		}
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data": map[string]interface{}{
			"list":  list,
			"count": count,
		},
	})
}

// Save 第三方协议接收帧,发送帧,读写帧
func (con FrameController) Save(ctx *gin.Context) {
	userToken := GetUserToken(ctx)
	frame := &model.Frame{}
	err := ctx.ShouldBindBodyWith(frame, binding.JSON)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的参数",
			"data":    err.Error(),
		})
		return
	}
	if frame.DecType != "DEC" {
		frame.DecType = "HEX"
	}
	list := make([]*model.FrameItemParam, 0)
	err = json.Unmarshal([]byte(frame.JsonDetail), &list)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "content解析失败" + err.Error(),
		})
		return
	}
	ppe := model.PPE{}
	exist, err := ppe.Exists(frame.PPEID)
	if !exist {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的 ppe_id",
			"data":    err,
		})
		return
	}
	if ppe.ProjectID != userToken.ProjectID {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "当前用户无权操作当前工程",
		})
		return
	}

	if ppe.ProtocolName != "CAN2.0B" && len(list) == 0 {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "帧内容不能为空",
		})
		return
	}

	code1 := model.AllowThirdCode1[ppe.ProtocolName]
	if code1 == "" {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "未找到当前设备协议匹配的code1",
		})
		return
	}

	frame.FrameItemParam = list
	frame.ProjectID = ppe.ProjectID
	now := tools.GetNow()
	err = frame.ValidateFrameV2(&ppe)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": err.Error(),
		})
		return
	}
	if frame.RelatedFrameID != 0 {
		if frame.FrameType != "recv" {
			ctx.JSON(200, gin.H{
				"code":    2,
				"message": "非接收帧不可以关联帧",
				"data":    "",
			})
			return
		}
		relatedFrame := &model.Frame{}
		exist, err = relatedFrame.Exists(frame.RelatedFrameID)
		if !exist {
			ctx.JSON(200, gin.H{
				"code":    2,
				"message": "无效的关联帧ID",
				"data":    err,
			})
			return
		}
		if relatedFrame.FrameType == "recv" {
			ctx.JSON(200, gin.H{
				"code":    2,
				"message": "关联帧不可以为接收帧",
				"data":    "",
			})
			return
		}
	}
	code3 := model.AllowFrameType[frame.FrameType]
	if code3 == "" {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的 frame_type",
			"data": map[string]interface{}{
				"frame_type": frame.FrameType,
			},
		})
		return
	}

	if frame.ID == 0 {
		/*--- 新增帧 ---*/
		frame.Status = 1
		frame.CreateTime = &now
		frame.UpdateTime = &now
		err = model.DB.Transaction(func(tx *gorm.DB) error {
			frame.Code1 = code1
			frame.Code2 = ppe.Code2
			frame.Code3 = code3
			err = tx.Omit("FrameItem").Create(frame).Error
			if err != nil {
				return err
			}
			frameItemInsert := make([]*model.FrameItem, 0) // 待新增变量
			for _, row := range frame.FrameItemParam {
				if row.InputMethod == 0 {
					continue
				}
				if row.Addr == "" {
					frameItemInsert = append(frameItemInsert, &model.FrameItem{
						Code1:         code1,
						Code2:         frame.Code2,
						Code3:         frame.Code3,
						Code4:         "",
						ProjectID:     ppe.ProjectID,
						PPEID:         ppe.ID,
						FrameID:       frame.ID,
						Addr:          "",
						FieldName:     row.FieldName,
						SpecType:      row.SpecType,
						Value:         row.Value,
						Endian:        row.Endian,
						RatioOperator: row.RatioOperator,
						Ratio:         row.Ratio,
						Fe:            row.Fe,
						Precision:     row.Precision,
						CreateTime:    &now,
						UpdateTime:    &now,
					})
				} else {
					updateData := make(map[string]interface{})
					updateData["field_name"] = row.FieldName
					updateData["spec_type"] = row.SpecType
					updateData["real_spec_type"] = row.RealSpecType
					updateData["endian"] = row.Endian
					updateData["ratio_operator"] = row.RatioOperator
					updateData["ratio"] = row.Ratio
					updateData["fe"] = row.Fe
					updateData["precision"] = row.Precision
					err = tx.Model(&model.FrameItem{}).Where("project_id = ? AND addr = ?", ppe.ProjectID, row.Addr).Updates(&updateData).Error
					if err != nil {
						return err
					}
				}
			}
			usedCode4 := make([]string, 0)
			err = tx.Model(&model.FrameItem{}).Where("project_id = ? AND code1 = ? AND code2 = ? AND code3 = ?", userToken.ProjectID, code1, frame.Code2, frame.Code3).Pluck("code4", &usedCode4).Error
			if err != nil {
				return err
			}
			availableCode4 := model.GetAvailableCode(model.AllCode4(), usedCode4)
			if len(availableCode4) < len(frameItemInsert) {
				return errors.New("当前通讯模块下的变量号已满 code4")
			}
			for i, row := range frameItemInsert {
				row.Code4 = availableCode4[i]
				row.Addr = fmt.Sprintf("%s-%s-%s-%s", row.Code1, row.Code2, row.Code3, row.Code4)
				for _, row2 := range frame.FrameItemParam {
					if row2.InputMethod == 1 && row2.FieldName == row.FieldName {
						//fmt.Printf("field=%s,addr=%s\n", row.FieldName, row.Addr)
						row2.Addr = row.Addr
					}
				}
			}
			if len(frameItemInsert) > 0 {
				err = tx.Select(
					"code1", "code2", "code3", "code4", "project_id", "ppe_id", "frame_id", "type", "addr", "field_name",
					"data_type", "spec_type", "value", "endian", "ratio", "multi_byte", "bool_bits", "create_time", "update_time").
					Create(&frameItemInsert).Error
			}

			// 补充更新变量地址到 json_detail 字段
			jsonB, _ := json.Marshal(&frame.FrameItemParam)
			err = tx.Model(&model.Frame{}).Where("id = ?", frame.ID).Update("json_detail", string(jsonB)).Error
			if err != nil {
				return err
			}
			return nil
		})
	} else {
		/*--- 修改帧 --- */
		// 注意事项!修改帧时不可修帧类型和所属ppe_id, code1,code2,code3都不能修改
		frame.UpdateTime = &now
		frameOld := &model.Frame{}
		exist2, err2 := frameOld.Exists(frame.ID)
		if !exist2 {
			ctx.JSON(200, gin.H{
				"code":    2,
				"message": "参数帧ID无效",
				"data": map[string]interface{}{
					"err": err2,
				},
			})
			return
		}
		err = model.DB.Transaction(func(tx *gorm.DB) error {
			err = tx.Model(&model.Frame{}).Where("id = ?", frame.ID).
				Omit("ppe_id", "code1", "code2", "code3", "frame_type", "status", "del", "create_time", "FrameItem").Updates(frame).Error
			if err != nil {
				return err
			}
			frameItemInsert := make([]*model.FrameItem, 0)
			for _, row := range list {
				if row.InputMethod == 0 {
					continue
				}
				if row.Addr == "" {
					frameItemInsert = append(frameItemInsert, &model.FrameItem{
						Code1:         frameOld.Code1,
						Code2:         frameOld.Code2,
						Code3:         frameOld.Code3,
						Code4:         "",
						ProjectID:     ppe.ProjectID,
						PPEID:         frameOld.PPEID,
						FrameID:       frameOld.ID,
						Addr:          "",
						FieldName:     row.FieldName,
						SpecType:      row.SpecType,
						Value:         row.Value,
						Endian:        row.Endian,
						RatioOperator: row.RatioOperator,
						Ratio:         row.Ratio,
						CreateTime:    &now,
						UpdateTime:    &now,
					})
				} else {
					updateData := make(map[string]interface{})
					updateData["field_name"] = row.FieldName
					updateData["spec_type"] = row.SpecType
					updateData["real_spec_type"] = row.RealSpecType
					updateData["endian"] = row.Endian
					updateData["ratio_operator"] = row.RatioOperator
					updateData["ratio"] = row.Ratio
					updateData["fe"] = row.Fe
					updateData["precision"] = row.Precision
					err = tx.Model(&model.FrameItem{}).Where("project_id = ? AND addr = ?", ppe.ProjectID, row.Addr).Updates(&updateData).Error
					if err != nil {
						return err
					}
				}
			}
			usedCode4 := make([]string, 0)
			err = tx.Model(&model.FrameItem{}).Where("project_id = ? AND code1 = ? AND code2 = ? AND code3 = ?", userToken.ProjectID, code1, frameOld.Code2, frameOld.Code3).Pluck("code4", &usedCode4).Error
			if err != nil {
				return err
			}
			availableCode4 := model.GetAvailableCode(model.AllCode4(), usedCode4)
			if len(availableCode4) < len(frameItemInsert) {
				return errors.New("当前通讯模块下的变量号已满 code4")
			}

			for i, row := range frameItemInsert {
				row.Code4 = availableCode4[i]
				row.Addr = fmt.Sprintf("%s-%s-%s-%s", row.Code1, row.Code2, row.Code3, row.Code4)
				for _, row2 := range frame.FrameItemParam {
					if row2.InputMethod == 1 && row2.FieldName == row.FieldName {
						//fmt.Printf("field=%s,addr=%s\n", row.FieldName, row.Addr)
						row2.Addr = row.Addr
					}
				}
			}

			if len(frameItemInsert) > 0 {
				err = tx.Select(
					"code1", "code2", "code3", "code4", "project_id", "ppe_id", "frame_id", "type", "addr", "field_name",
					"data_type", "spec_type", "value", "endian", "ratio", "multi_byte", "bool_bits", "create_time", "update_time").
					Create(&frameItemInsert).Error
				if err != nil {
					return err
				}
			}

			// 补充更新变量地址到 json_detail 字段
			jsonB, _ := json.Marshal(&frame.FrameItemParam)
			err = tx.Model(&model.Frame{}).Where("id = ?", frame.ID).Update("json_detail", string(jsonB)).Error
			if err != nil {
				return err
			}
			return nil
		})
	}
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    10,
			"message": "sql事务失败 " + err.Error(),
			"data":    map[string]interface{}{},
		})
		return
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data":    map[string]interface{}{},
	})
}

func (con FrameController) Detail(ctx *gin.Context) {
	param := struct {
		Id int `json:"id" binding:"required"`
	}{}
	err := ctx.ShouldBindBodyWith(&param, binding.JSON)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的参数",
			"data":    err.Error(),
		})
		return
	}

	info := model.Frame{}
	err = model.DB.Model(&model.Frame{}).Where("id = ?", param.Id).First(&info).Error
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    6,
			"message": err.Error(),
		})
		return
	}
	info.JsonDetail, err = model.GetLatestFrameJsonDetail(&info)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "获取帧内容数据失败" + err.Error(),
			"data":    map[string]interface{}{},
		})
		return
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data": map[string]interface{}{
			"info": info,
		},
	})
}

func (con FrameController) Delete(ctx *gin.Context) {
	param := struct {
		Id int `json:"id" binding:"required"`
	}{}
	err := ctx.ShouldBindBodyWith(&param, binding.JSON)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的参数",
			"data":    err.Error(),
		})
		return
	}
	info := model.Frame{}

	err = model.DB.Model(&model.Frame{}).Where("id = ?", param.Id).First(&info).Error

	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    6,
			"message": err.Error(),
		})
		return
	}

	err = model.DB.Transaction(func(tx *gorm.DB) error {
		err = tx.Where("id = ?", param.Id).Delete(&model.Frame{}).Error
		if err != nil {
			return err
		}
		err = tx.Where("frame_id = ?", param.Id).Delete(&model.FrameItem{}).Error
		if err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    10,
			"message": err.Error(),
		})
		return
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data":    map[string]interface{}{},
	})
}

// Send 第三方帧发送, 事件触发帧, 单点发送
func (con FrameController) Send(ctx *gin.Context) {
	param := struct {
		Id int `json:"id" binding:"required"`
	}{}
	err := ctx.ShouldBindBodyWith(&param, binding.JSON)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的参数",
			"data":    err.Error(),
		})
		return
	}

	frame := &model.Frame{}
	err = model.DB.Model(&model.Frame{}).Where("id = ?", param.Id).Limit(1).Find(frame).Error
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    6,
			"message": err.Error(),
		})
		return
	}
	if frame.ID == 0 {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "无效的帧ID",
			"data":    map[string]interface{}{},
		})
		return
	}
	if frame.FrameType == "recv" {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "接收帧不能发送",
			"data":    map[string]interface{}{},
		})
		return
	}
	err = json.Unmarshal([]byte(frame.JsonDetail), &frame.FrameItemParam)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": "帧内容json解析失败",
			"data":    err.Error(),
		})
		return
	}
	// 判断设备是否运行中
	ppe, ok := model.RunningPPEMap.Get(frame.PPEID)
	if !ok {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": fmt.Sprintf("设备未运行 ppe_id=%d", frame.PPEID),
			"data":    map[string]interface{}{},
		})
		return
	}
	if ppe.RunningState != 2 {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": fmt.Sprintf("设备未运行 ppe_id=%d, %s", frame.PPEID, ppe.Detail),
			"data":    map[string]interface{}{},
		})
		return
	}
	rawData := ""
	switch ppe.ProtocolName {
	case "CAN2.0B":
		list := frame.FrameItemParam
		data, err := model.CreateFrameRawData(list)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("生成数据部分失败; %s", err.Error()),
				"data":    map[string]interface{}{},
			})
			return
		}
		fullData, err := model.CreateCanFrame(frame, data)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("生成CAN帧失败; %s", err.Error()),
				"data":    map[string]interface{}{},
			})
			return
		}
		rawData = tools.ByteArrayToHexStr(fullData)
		j_log.LogInfo([]interface{}{fmt.Sprintf("【send】%s, ppe_id=%d len=%d %s", ppe.ProtocolName, ppe.ID, len(fullData), tools.ByteArrayToHexStr(fullData))})
		_, err = ppe.TcpClient.Connection.Write(fullData)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("tcp发送失败:%s", err.Error()),
				"data":    map[string]interface{}{},
			})
			return
		}
	case "RS485":
		list := frame.FrameItemParam
		data, err := model.CreateFrameRawData(list)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("帧生成原始数据失败; %s", err.Error()),
				"data":    err.Error(),
			})
			return
		}
		rawData = tools.ByteArrayToHexStr(data)
		port := *(ppe.RS485Client)
		_, err = port.Write(data)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("串口写入失败:%s", err.Error()),
				"data":    map[string]interface{}{},
			})
			return
		}
	case "MODBUS RTU":
		fallthrough
	case "MODBUS TCP":
		switch frame.FunctionCode {
		case "0F":
			list := frame.FrameItemParam
			if ppe.ProtocolName == "MODBUS RTU" {
				err = ppe.ModbusRTUClient.SetUnitId(frame.SlaveID)
			} else {
				err = ppe.ModbusTCPClient.SetUnitId(frame.SlaveID)
			}
			if err != nil {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("SetUnitId失败:%s", err.Error()),
					"data":    map[string]interface{}{},
				})
				return
			}
			startAddr := frame.StartAddr
			data, err := model.CreateFrameCoilsRawData(list)
			if err != nil {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("CreateFrameCoilsRawData失败:%s", err.Error()),
					"data":    map[string]interface{}{},
				})
				return
			}
			if len(data) != frame.Quantity {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("写入的线圈个数与原始数据字节数不符"),
					"data":    map[string]interface{}{},
				})
				return
			}
			if ppe.ProtocolName == "MODBUS RTU" {
				err = ppe.ModbusRTUClient.WriteCoils(startAddr, data)
			} else {
				err = ppe.ModbusTCPClient.WriteCoils(startAddr, data)
			}
			if err != nil {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("WriteCoils失败:%s", err.Error()),
					"data":    map[string]interface{}{},
				})
			}
		case "10":
			list := frame.FrameItemParam
			if ppe.ProtocolName == "MODBUS RTU" {
				err = ppe.ModbusRTUClient.SetUnitId(frame.SlaveID)
			} else {
				err = ppe.ModbusTCPClient.SetUnitId(frame.SlaveID)
			}
			if err != nil {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("SetUnitId失败:%s", err.Error()),
					"data":    map[string]interface{}{},
				})
				return
			}
			startAddr := frame.StartAddr
			data, err := model.CreateFrameRawData(list)
			if err != nil {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("CreateFrameRawData失败:%s", err.Error()),
					"data":    map[string]interface{}{},
				})
				return
			}
			if len(data) != frame.Quantity*2 {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("写入的寄存器个数与原始数据字节数不符"),
					"data":    map[string]interface{}{},
				})
				return
			}
			if ppe.ProtocolName == "MODBUS RTU" {
				err = ppe.ModbusRTUClient.WriteBytes(startAddr, data)
			} else {
				err = ppe.ModbusTCPClient.WriteBytes(startAddr, data)
			}
			if err != nil {
				ctx.JSON(200, gin.H{
					"code":    1,
					"message": fmt.Sprintf("WriteBytes失败:%s", err.Error()),
					"data":    map[string]interface{}{},
				})
				return
			}
		default:
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("暂不支持的modbus功能码:%s", frame.FunctionCode),
				"data":    map[string]interface{}{},
			})
			return
		}
	case "TCP/IP":
		list := frame.FrameItemParam
		data, err := model.CreateFrameRawData(list)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("帧生成原始数据失败; %s", err.Error()),
				"data":    err.Error(),
			})
			return
		}
		rawData = tools.ByteArrayToHexStr(data)
		_, err = ppe.TcpClient.Connection.Write(data)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("tcp发送失败:%s", err.Error()),
				"data":    map[string]interface{}{},
			})
			return
		}
	//case "OPC Client":

	//case "OPC Server":

	case "PLC":
		list := frame.FrameItemParam
		startAddr := frame.StartAddr
		data, err := model.CreateFrameRawData(list)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("帧生成原始数据失败; %s", err.Error()),
				"data":    map[string]interface{}{},
			})
			return
		}
		if len(data) != frame.Quantity {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("PLC写入的点位个数与帧字节长度不符"),
				"data":    map[string]interface{}{},
			})
			return
		}
		err = (*ppe.PLCSnap7Client).AGWriteDB(frame.DBNumber, int(startAddr), frame.Quantity, data)
		if err != nil {
			ctx.JSON(200, gin.H{
				"code":    1,
				"message": fmt.Sprintf("PLC写入失败:%s", err.Error()),
				"data":    map[string]interface{}{},
			})
			return
		}
	default:
		ctx.JSON(200, gin.H{
			"code":    1,
			"message": fmt.Sprintf("暂不支持此协议 %s", ppe.ProtocolName),
			"data":    map[string]interface{}{},
		})
		return
	}

	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data": map[string]interface{}{
			"rawData": rawData,
		},
	})
}

func (con FrameController) RelateAvailableList(ctx *gin.Context) {
	userToken := GetUserToken(ctx)
	param := struct {
		PPEID int `json:"ppe_id"`
		model.QueryData
	}{}
	err := ctx.ShouldBindBodyWith(&param, binding.JSON)
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    2,
			"message": "无效的参数",
			"data":    err.Error(),
		})
		return
	}

	tx := model.DB.Where("project_id = ? AND frame_type != ?", userToken.ProjectID, "recv")
	if param.PPEID != 0 {
		tx.Where("ppe_id = ?", param.PPEID)
	}

	var count int64
	list := make([]*model.FrameSlim, 0)
	err = tx.Model(&model.FrameSlim{}).Count(&count).Error
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    6,
			"message": err.Error(),
		})
		return
	}
	err = tx.Preload("PPEInfo").Order("id desc").Offset(param.StartPage()).Limit(param.PageSize).Find(&list).Error
	if err != nil {
		ctx.JSON(200, gin.H{
			"code":    6,
			"message": err.Error(),
		})
		return
	}
	for _, row := range list {
		if row.PPEInfo == nil {
			row.PPEInfo = &model.PPE{}
		}
	}
	ctx.JSON(200, gin.H{
		"code":    0,
		"message": "success",
		"data": map[string]interface{}{
			"list":  list,
			"count": count,
		},
	})
}
